package com.friend.uu;

import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.RequiresApi;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public class P2pActivity extends Activity implements View.OnClickListener {

    private static final int REQUEST_CODE_ACTIVITY = 1;
    private static final int REQUEST_CODE_PERMISSIONS = 2;
    private static final String[] PERMISSIONS =
            new String[]{Manifest.permission.INTERNET,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE};
    private static final String PREF_IP = "p2p.ip";
    private static final String PREF_PORT = "p2p.port";
    private static final String PREF_SHARE_KEY = "p2p.key";
    private EditText etRemoteIp, etPort, etKey;
    private TextView tvLocalIp, tvLog;
    private int mPort;
    private byte mKey;
    Button btnServer;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_p2p);

        if (allPermissionsDenied()) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                requestPermissions(PERMISSIONS, REQUEST_CODE_PERMISSIONS);
            }
        }
        bindView();
    }

    private boolean allPermissionsDenied() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return false;
        }
        for (String p : PERMISSIONS) {
            if (checkSelfPermission(p) != PackageManager.PERMISSION_GRANTED) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                           int[] grantResults) {
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsDenied()) {
                finish();
            }
        }
    }

    private void bindView() {
        etRemoteIp = findViewById(R.id.et_p2p_remote_ip);
        etPort = findViewById(R.id.et_p2p_port);
        etKey = findViewById(R.id.et_p2p_key);
        tvLocalIp = findViewById(R.id.tv_p2p_local_ip);
        tvLog = findViewById(R.id.tv_p2p_log);
        Button btnShare = findViewById(R.id.btn_p2p_share);
        btnServer = findViewById(R.id.btn_p2p_server);
        btnShare.setOnClickListener(this);
        btnServer.setOnClickListener(this);
        findViewById(R.id.btn_p2p_clear).setOnClickListener(this);
        findViewById(R.id.btn_p2p_back).setOnClickListener(this);
        // init data
        showLocalAddress();
        readPreferences();
    }

    private void showLocalAddress() {
        StringBuilder ips = new StringBuilder();
        try {
            Enumeration<NetworkInterface> nis =
                    NetworkInterface.getNetworkInterfaces();
            while (nis.hasMoreElements()) {
                NetworkInterface ni = nis.nextElement();
                Enumeration<InetAddress> addresses = ni.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress address = addresses.nextElement();
                    if (address instanceof Inet4Address &&
                            !address.isLoopbackAddress()) {
                        ips.append(" ").append(address.getHostAddress());
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        tvLocalIp.setText(getString(R.string.local_host, ips));
    }

    /**
     * Read preferences
     **/
    private void readPreferences() {
        SharedPreferences pref = getPreferences(0);
        etRemoteIp.setText(pref.getString(PREF_IP, "127.0.0.1"));
        etKey.setText(String.valueOf(pref.getInt(PREF_SHARE_KEY, 22)));
        etPort.setText(String.valueOf(pref.getInt(PREF_PORT, 8888)));
    }

    /**
     * Save preferences
     **/
    private void savePreferences() {
        String ip = etRemoteIp.getText().toString().trim();
        int port = 8888;
        byte shareKey = 22;
        try {
            port = Integer.parseInt(etPort.getText().toString());
            shareKey = Byte.parseByte(etKey.getText().toString());
        } catch (NumberFormatException ignore) {
        }
        getPreferences(0).edit()
                .putString(PREF_IP, ip)
                .putInt(PREF_PORT, port)
                .putInt(PREF_SHARE_KEY, shareKey)
                .apply();
    }

    @Override
    protected void onStop() {
        super.onStop();
        savePreferences();
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        if (id == R.id.btn_p2p_clear) {
            tvLog.setText("");
        } else if (id == R.id.btn_p2p_back) {
            finish();
        } else if (id == R.id.btn_p2p_share) {
            sendFile();
        } else if (id == R.id.btn_p2p_server) {
            showLocalAddress();
            openCloseServer();
        }
    }

    private void sendFile() {
        Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.setType("*/*");
        startActivityForResult(intent, REQUEST_CODE_ACTIVITY);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode,
                                    final Intent data) {
        if (requestCode == REQUEST_CODE_ACTIVITY && resultCode == RESULT_OK) {
            // Send file
            Intent service = new Intent(this, P2pService.class);
            String mRemoteIp = etRemoteIp.getText().toString();
            try {
                mPort = Integer.parseInt(etPort.getText().toString());
                mKey = Byte.parseByte(etKey.getText().toString());
            } catch (NumberFormatException e) {
                addLog(e.getMessage());
                return;
            }
            service.putExtra(P2pService.EXTRA_FILE, data.getData().toString())
                    .putExtra(P2pService.EXTRA_IP, mRemoteIp)
                    .putExtra(P2pService.EXTRA_PORT, mPort)
                    .putExtra(P2pService.EXTRA_KEY, mKey)
                    .setAction(P2pService.ACTION_SEND);
            startService(service);
        }
    }

    boolean serviceIsRunning = false;

    private void openCloseServer() {
        Intent service = new Intent(this, P2pService.class);
        if (serviceIsRunning) {
            stopService(service);
        } else {
            try {
                mPort = Integer.parseInt(etPort.getText().toString());
                mKey = Byte.parseByte(etKey.getText().toString());
            } catch (NumberFormatException e) {
                addLog(e.getMessage());
                return;
            }
            service.putExtra(P2pService.EXTRA_PORT, mPort)
                    .putExtra(P2pService.EXTRA_KEY, mKey)
                    .setAction(P2pService.ACTION_RECEIVE);
            startService(service);
        }
        serviceIsRunning = !serviceIsRunning;
        int strId = serviceIsRunning ? R.string.close_server : R.string.open_server;
        btnServer.setText(strId);
    }

    private void addLog(String log) {
        log = tvLog.getText() + "\n" + log;
        tvLog.setText(log);
    }
}
